#ifndef LIBRARY_FUNCTIONS_H
#define LIBRARY_FUNCTIONS_H

#include "GOAL.h"

#include <string>
#include <map>

namespace GOAL
{
  /// check to see if the object exists in the specified root
  /// this follows a more natural path and should not be preceded
  /// by a delimiter ('.') for the root folder inclusion. Instead
  /// specify paths like this "GOAL.Primitives.String" for instance.
  bool objectExists (const std::string& path, RootFolder& root);

  /// get object from the root folder
  Udm::Object getObjectByPath (const std::string& path, 
    RootFolder& root);

  /// get object by the specified path, using the current as the
  /// current object to look at, and the path_relative_to as a root
  /// for the path info. This should allow for a library to be
  /// embedded into another paradigm - though it obviously hasn't
  /// been tested.
  Udm::Object getObjectByPath (const std::string& path, 
    ModuleAdapter& current, Udm::Object& path_relative_to);

  /// get parent path
  std::string getParentPath (const std::string& path);

  /// get child name (path - parent path)
  std::string getChildName (const std::string& path);

  /// convert to a directory path
  std::string convertToDirectory (std::string path);

  /// convert to a namespace
  std::string convertToNamespace (std::string path);
  void writeModulePathToStream (std::ostream & output, std::string& path, 
                               std::string& type, int& tabs);
  void createDirectory (std::string path);

  /**
   * @class Library
   * @brief a class for using and creating new libraries
   */

  class Library
  {
  public:
    class Primitives
    {
    public:
      static const int Integer;
    };

    /// constructor - necessary to use the position info
    Library ();

    /// destructor
    ~Library ();

    static const std::string const_lookups[];

    // function for reading a predefined library
    void read (const std::string& name, Udm::SmartDataNetwork& library);

    // create a primitive class
    Udm::Object createPrimitive (const std::string& primitive, GOAL::RootFolder& root);

    // create a copy constructor function
    Udm::Object createCopyConstructor (GOAL::Class& newClass);

    // create a size function
    Udm::Object createSizeFunction (GOAL::Class& newClass, GOAL::Class& integer);

    // get a GOAL.Primitives.Integer class. If it doesn't exist in the
    // model, then create one
    Udm::Object getInteger (GOAL::RootFolder& root);

    // get the primitive parent. If it doesn't exist in the model,
    // then create one
    Udm::Object getParent (const std::string& primitive, GOAL::RootFolder& root);

    // create a length function. used by GOAL.Primitives.String.
    Udm::Object createLengthFunction (GOAL::Class& newClass, GOAL::Class& integer);
  private:
    static const int NUM_LIBRARIES = 7;
    std::map <std::string,std::string> positions_;
  };
}

#endif